-- Copyright (c) 2010, Pavel Kovar
-- All rights reserved.
--
---------------------------------------------------------------------------------------
-- This file is a part of the Witch Navigator project

-- cor_mac
-- Implemented
--   * Integrators for six universals correlators
--
-- Consecutive processing in single HW 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity cor_mac is
    Port ( clk_dsp : in STD_LOGIC;
           cos_in : in  STD_LOGIC_VECTOR (7 downto 0);
           sin_in : in  STD_LOGIC_VECTOR (7 downto 0);
           sig_real : in  STD_LOGIC_VECTOR (7 downto 0);
           sig_imag : in  STD_LOGIC_VECTOR (7 downto 0);
           prn_e : in  STD_LOGIC;
           prn_l : in  STD_LOGIC;
           tic_e : in  STD_LOGIC;
           tic_l : in  STD_LOGIC;
           cor_e_out : out STD_LOGIC_VECTOR(31 downto 0);
           cor_l_out : out STD_LOGIC_VECTOR(31 downto 0)
       );
end cor_mac;

architecture Behavioral of cor_mac is

signal sig_real_reg0, sig_imag_reg0: std_logic_vector(7 downto 0):= (others => '0'); 
signal mult_real4, mult_imag4: std_logic_vector(14 downto 0);
signal prn_e1, prn_e2, prn_e3, prn_e4: std_logic:= '0';
signal prn_l1, prn_l2, prn_l3, prn_l4: std_logic:= '0';
signal accer0, accer1, accer2, accer3, accer4: std_logic_vector(31 downto 0):= (others => '0');  
signal accei0, accei1, accei2, accei3, accei4: std_logic_vector(31 downto 0):= (others => '0');  
signal acclr0, acclr1, acclr2, acclr3, acclr4: std_logic_vector(31 downto 0):= (others => '0');  
signal accli0, accli1, accli2, accli3, accli4: std_logic_vector(31 downto 0):= (others => '0');  
signal t_e1, t_l1: std_logic;

component cmult
	port (
	ar: IN std_logic_VECTOR(7 downto 0);
	ai: IN std_logic_VECTOR(7 downto 0);
	br: IN std_logic_VECTOR(7 downto 0);
	bi: IN std_logic_VECTOR(7 downto 0);
	clk: IN std_logic;
	pr: OUT std_logic_VECTOR(14 downto 0);
	pi: OUT std_logic_VECTOR(14 downto 0));
end component;

-- a input: signed, 32 bit, 
-- b input: signed, 15 bit
-- AddMode: add subtract
component sacc
	port (
	a: IN std_logic_VECTOR(31 downto 0);
	b: IN std_logic_VECTOR(14 downto 0);
	clk: IN std_logic;
	add: IN std_logic;
	s: OUT std_logic_VECTOR(31 downto 0));
end component;

begin

process (clk_dsp)
begin
	if clk_dsp'event and clk_dsp = '1' then
		-- signals sig_real and sig_imag are registered in cor_timmeing one clk_dsp before
		-- phase cycle begining
		sig_real_reg0 <= sig_real;
		sig_imag_reg0 <= sig_imag;
		
		prn_e1 <= prn_e;		prn_l1 <= prn_l;
		prn_e2 <= prn_e1;		prn_l2 <= prn_l1;
		prn_e3 <= prn_e2;		prn_l3 <= prn_l2;
		prn_e4 <= prn_e3;		prn_l4 <= prn_l3;
		
		t_e1 <= tic_e;		t_l1 <= tic_l;

		accer1 <= accer0;		accei1 <= accei0;		acclr1 <= acclr0;		accli1 <= accli0;
		if t_e1 = '1' then
			accer2 <= "00000000000000000000000000000000";
			accei2 <= "00000000000000000000000000000000";
		else
			accer2 <= accer1; accei2 <= accei1;
		end if;
		
		if t_l1 = '1' then
			acclr2 <= "00000000000000000000000000000000";
			accli2 <= "00000000000000000000000000000000";
		else
			acclr2 <= acclr1; accli2 <= accli1;
		end if;
		
		accer3 <= accer2;		accei3 <= accei2;		acclr3 <= acclr2;		accli3 <= accli2;
		accer4 <= accer3;		accei4 <= accei3;		acclr4 <= acclr3;		accli4 <= accli3;
	end if;
end process;

cor_e_out(15 downto 0) <= accer0(28 downto 13);
cor_e_out(31 downto 16) <= accei0(28 downto 13);
cor_l_out(15 downto 0) <= acclr0(28 downto 13);
cor_l_out(31 downto 16) <= accli0(28 downto 13);

-- complex multiplier
-- latency 4
cmul : cmult
		port map (
			ar => sig_real_reg0,
			ai => sig_imag_reg0,
			br => cos_in,
			bi => sin_in,
			clk => clk_dsp,
			pr => mult_real4,
			pi => mult_imag4);

-- early real accumulator
-- latency 2
ereal : sacc
		port map (
			a => accer4,
			b => mult_real4,
			clk => clk_dsp,
			add => prn_e4,
			s => accer0);

-- early imaginary accumulator
-- latency 2			
eimag : sacc
		port map (
			a => accei4,
			b => mult_imag4,
			clk => clk_dsp,
			add => prn_e4,
			s => accei0);

-- late real accumulator
-- latency 2
lreal : sacc
		port map (
			a => acclr4,
			b => mult_real4,
			clk => clk_dsp,
			add => prn_l4,
			s => acclr0);

-- late imaginary accumulator
-- latency 2
limag : sacc
		port map (
			a => accli4,
			b => mult_imag4,
			clk => clk_dsp,
			add => prn_l4,
			s => accli0);
end Behavioral;

